package job

import (
	"context"
	"fmt"
	log "github.com/golang/glog"
	"im_backend/api/comet"
	pb "im_backend/api/logic"
	"im_backend/api/protocol"
	"im_backend/pkg/bytes"
)

func (j *Job) push(ctx context.Context, pushMsg *pb.PushMsg) (err error) {
	switch pushMsg.Type {
	case pb.PushMsg_MSGTYPE_PUSH:
		err = j.pushKeys(pushMsg.Operation, pushMsg.Server, pushMsg.Keys, pushMsg.Msg, pushMsg.From, pushMsg.Seq)
	case pb.PushMsg_MSGTYPE_ROOM:
		err = j.getRoom(pushMsg.Room).Push(pushMsg.Operation, pushMsg.Msg)
	case pb.PushMsg_MSGTYPE_BROADCAST:
		err = j.broadcast(pushMsg.Operation, pushMsg.Msg)
	default:
		err = fmt.Errorf("no match push type: %s", pushMsg.Type)
	}
	return
}

func (j *Job) pushKeys(operation int32, serverID string, subKeys []string, body []byte, from, seq int64) (err error) {
	buf := bytes.NewWriterSize(len(body) + 64)
	p := &protocol.Proto{
		Version: 1,
		Op:      operation,
		Body:    body,
		From:    from,
		Seq:     seq,
	}
	p.WriteTo(buf)
	p.Body = buf.Buffer()
	p.Op = protocol.OpRaw
	var args = comet.PushMsgReq{
		Keys:    subKeys,
		ProtoOp: operation,
		Proto:   p,
	}
	if c, ok := j.cometServers[serverID]; ok {
		if err = c.Push(&args); err != nil {
			log.Errorf("c.Push(%v) serverID:%s error(%v)", args, serverID, err)
		}
		log.Infof("pushKey:%s comets:%d", serverID, len(j.cometServers))
	}
	return
}

func (j *Job) broadcast(operation int32, body []byte) (err error) {
	buf := bytes.NewWriterSize(len(body) + 64)
	p := &protocol.Proto{
		Version: 1,
		Op:      operation,
		Body:    body,
	}
	p.WriteTo(buf)
	p.Body = buf.Buffer()
	p.Op = protocol.OpRaw
	comets := j.cometServers
	var args = comet.BroadcastReq{
		ProtoOp: operation,
		Proto:   p,
	}
	for serverID, c := range comets {
		if err = c.Broadcast(&args); err != nil {
			log.Errorf("c.Broadcast(%v) serverID:%s error(%v)", args, serverID, err)
		}
	}
	log.Infof("broadcast comets:%d", len(comets))
	return
}

func (j *Job) broadcastRoomRawBytes(roomID string, body []byte) (err error) {
	args := comet.BroadcastRoomReq{
		RoomID: roomID,
		Proto: &protocol.Proto{
			Version: 1,
			Op:      protocol.OpRaw,
			Body:    body,
		},
	}
	comets := j.cometServers
	for serverID, c := range comets {
		if err = c.BroadcastRoom(&args); err != nil {
			log.Errorf("c.BroadcastRoom(%v) roomID:%s serverID:%s error(%v)", args, roomID, serverID, err)
		}
	}
	log.Infof("broadcastRoom comets:%d", len(comets))
	return
}
